/* 
 * DA5_Midterm.c 
 * 
 * Created: 4/2/2014 1:53:48 AM 
 *  Author: Jared 
 * 
 *  C AVR program that will read the temperature from an LM34 and display 
 * it in Fahrenheit every 1 second.  Also will display the temperature to  
 * 7-segment displays. 
 * 
 * 
 */ 
    
#define F_CPU 8000000UL 
#include <avr/io.h> 
#include <avr/interrupt.h>  
  
#define MOSI 5 
#define SCK 7 
#define SS 4 
  
int temp = 0;                                               // Value to hold the temperature 
int blah = 0; 
   
void USARTInit(void); void ReadTemp(void); void ADCConvert(void); void DisplayTemp(uint8_t); void Display7Seg(void); void execute(unsigned char, uint8_t);  void Delay(void); 
    
     
int main(void) 
{ 
    DDRC = 0;                                               // Port C set as input for ADC 
    DDRB = 0xFF;                                            // Port B set as output 
    EIMSK = 0x01;                                           // enable int0 (PD2) 
    sei();                                                  // enable interrupts 
                   
    USARTInit();  
    //ReadTemp();    
            
        while(1) 
        { 
            ADCConvert(); 
            DisplayTemp(temp); 
            Delay();                                       
            Display7Seg(); 
        } 
} 
    
void USARTInit(void){    
    UCSR0B = (1 << RXEN0) | (1 << TXEN0);                   // Initialize USART 
    UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);                 // Char size = 8, 1 stop bit, asynchronous  
    UBRR0L = 0x33;                                          // Baud Rate = 9600,  X = (500kHz/BR) - 1, Fosc = 8Mhz 
} 
    
void ReadTemp(void){ 
    while (! (UCSR0A & (1 << RXC0)));                    // Wait until new data, RXC high 
    PORTC = UDR0;                                       // Read to PortC 
} 
  
void DisplayTemp(uint8_t ch){ 
    while (! (UCSR0A & (1 << UDRE0)));                        // Check if UDRE is high 
        UDR0 = ch;                                          // Transmit to temp 
} 
    
void ADCConvert(void){ 
    ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);  // ADC enable, ck/64 
    ADMUX |= (1 << REFS0) | (1 << REFS1) | (1 << ADLAR);    // 2.56 Vref, ADC0 single-ended, left-justified 
        
    ADCSRA |= (1 << ADSC);                                  // Start conversion 
    while ((ADCSRA & (1 << ADIF)) == 0);                  // Wait for end of conversion 
        temp = ADCH; 
		temp = temp*5;										// Convert to degrees.  1 degree = 10mV
} 
    
void Display7Seg(void){ 
    DDRB = (1 << MOSI) | (1 << SCK) | (1 << SS);          // MOSI and SCK are output 
    SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);          // enable SPI as master 
        
    execute(0x09, 0b00000011);                              // enable decoding for digits 1,2 
    execute(0x0B, 0x04);                                    // scan four 7-segments 
    execute(0x0C, 0x01);                                    // turn on chip 
    
	execute(0x05, temp/1000);                               // display temperature 
	execute(0x04, temp%1000/100);                           // 3rd digit 
	execute(0x03, temp%100/10);                             // 2nd digit 
	execute(0x02, temp%10);                                 // 1st digit 
} 
    
void execute(unsigned char cmd, uint8_t data){ 
    PORTB &= (1 << SS);                                     // initializing packet, pull SS low 
        
    SPDR = cmd;                                             // start cmd transmission 
    while (!(SPSR & (1 << SPIF)));                          // wait transfer finish      
        
    SPDR = data;                                            // start data transmission 
    while (!(SPSR & (1 << SPIF)));                          // wait transfer finish 
        
    PORTB |= (1 << SS);                                     // terminate packet, pull SS low 
} 
    
void Delay(void) 
{ 
        TCNT1 = 0x18B8;                     // TCNT = 2^n - x/s = 2^8 - (1.0sec delay * 8MHz)/64 
        TCCR1A = 0x00;                      // 
        TCCR1B = 0x03;                      // CS02 = 0, CS01 = 1, CS00 = 0,  0b011 = 3 
        while((TIFR1&0x01) == 0){           // While TOV1 is not set 
            //wait 
        } 
        TIFR1 = 0x01;                        
        return; 
} 
    
ISR(INT0_vect){                             // delay subroutine 
        blah++; 
} 